package com.atguigu.common.validator;



import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author lvling
 */
public class ValuedEnumValidator implements ConstraintValidator<ValuedEnum, Object> {

    private Class<? extends Enum> enumType;

    private String field;

    private static final Map<String, Field> fieldCache = new ConcurrentHashMap();

    @Override
    public void initialize(ValuedEnum constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
        this.enumType = constraintAnnotation.type();

        this.field = constraintAnnotation.field();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
        if (null == value) {
            return true;
        }
        Object[] enumConstants = enumType.getEnumConstants();
        String fieldCacheKey = enumType.getTypeName() + "#" + field;
        Field field = fieldCache.get(fieldCacheKey);
        if (field == null) {
            synchronized (enumType) {
                field = fieldCache.get(fieldCacheKey);
                if (field == null) {
                    field = ValidationUtils.getDeclaredField(enumType, this.field);
                    if (field == null) {
                        return false;
                    }
                    if (!field.isAccessible()) {
                        field.setAccessible(true);
                    }
                    fieldCache.put(fieldCacheKey, field);
                }
            }
        }
        try {
            for (Object enumValue : enumConstants) {
                Object enumFieldValue = field.get(enumValue);
                if (enumFieldValue.equals(value)) {
                    return true;
                }
            }
        } catch (IllegalAccessException e) {
            return false;
        }
        return false;
    }
}
